﻿// Decompiled with JetBrains decompiler
// Type: DnProcessSimulateCommands.StopZero.CApStopZeroMotionDataGenerator
// Assembly: DnProcessSimulateCommands, Version=2402.0.0.890, Culture=neutral, PublicKeyToken=null
// MVID: A885D881-AEDF-447E-852A-6F13102E089C
// Assembly location: C:\Program Files\Tecnomatix_2402\eMPower\DotNetCommands\DnProcessSimulateCommands.dll

using DnProcessSimulateCommands.CycleTimeReport;
using DnProcessSimulateCommands.StopZero.Resources;
using EngineeringInternalExtension;
using EngineeringInternalExtension.DataTypes;
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using Tecnomatix.Engineering;
using Tecnomatix.Engineering.Olp;
using Tecnomatix.Engineering.Olp.PrivateImplementationDetails;


namespace DnProcessSimulateCommands.StopZero;

public sealed class CApStopZeroMotionDataGenerator
{
  private List<CApStopZeroSafetyVolume> _safetyVolumes;
  private readonly ITxRoboticLocationOperation _startLocation;
  private readonly ITxRoboticLocationOperation _endLocation;
  private bool _isDataGenerationSuccessful;
  private ITxRobot _robot;
  private readonly bool _accuracyMode;
  private readonly double _timeInterval;
  private readonly int _stopType;
  private TxRRSServicesProvider _rrsServiceProvider;
  private bool _isRCSTurnedOffForSimulationActions;
  private TxTransformation _rrsWorldFrame;
  private TxSimulationPlayer _player;
  private double _originalTimeInterval;
  private bool _originalIgnoreSignals;
  private bool _originalStopOnCollision;
  private CApCTRToggleCmd _cycleTimeReport;
  private bool _originalIsCycleTimeReportActivated;
  private List<List<TxRobotSimulationStopMotionData>> _stopMotionData;
  private CApStopZeroProgressReporter _progressReporter;
  private readonly Func<bool> _isGenerationStopped;
  private CApStopZeroMotionDataGenerator.SimulationPhase _simulationPhase;

  public CApStopZeroMotionDataGenerator(
    ITxRoboticLocationOperation start,
    ITxRoboticLocationOperation end,
    bool accuracyMode,
    double timeInterval,
    int stopType,
    List<CApStopZeroSafetyVolume> safetyVolumes,
    CApStopZeroProgressReporter progressReporter,
    Func<bool> isGenerationStopped)
  {
    this._startLocation = start;
    this._endLocation = end;
    this._robot = CApStopZeroUtilities.GetAssignedRobot(this._startLocation ?? this._endLocation);
    this._accuracyMode = accuracyMode;
    this._timeInterval = timeInterval;
    this._stopType = stopType;
    this._safetyVolumes = safetyVolumes;
    this._progressReporter = progressReporter;
    this._isGenerationStopped = isGenerationStopped;
  }

  public bool Generate(
    out List<List<TxRobotSimulationStopMotionData>> stopMotionData)
  {
    this._stopMotionData = new List<List<TxRobotSimulationStopMotionData>>();
    this.InitRRS();
    this.InitPlayer();
    this.SetSafetyVolumesToRRS();
    try
    {
      this._player.PlayWithoutRefresh();
    }
    catch (Exception ex)
    {
    }
    finally
    {
      this.PlayerRestore();
      this.RestoreRRS();
      this.ShowErrorMessage();
    }
    stopMotionData = this._stopMotionData;
    return this._isDataGenerationSuccessful;
  }

  private void ShowErrorMessage()
  {
    if (this._isDataGenerationSuccessful || this._isGenerationStopped())
      return;
    int num = (int) TxMessageBox.ShowModal(StopZeroStringTable.EndLocationNotReachedError, StopZeroStringTable.CommandName, MessageBoxButtons.OK, MessageBoxIcon.Hand);
  }

  private void SetSafetyVolumesToRRS()
  {
    TxRRSServicesProviderEx.SetStopSafetyVolumes(this._rrsServiceProvider, this._safetyVolumes.ConvertAll<KeyValuePair<int, TxTransformation>>((Converter<CApStopZeroSafetyVolume, KeyValuePair<int, TxTransformation>>) (volume => new KeyValuePair<int, TxTransformation>(volume.Id, volume.SphereInfo.CenterRelativeToTCP))));
  }

  private TxTransformation GetRrsFrame()
  {
    ITxRoboticControllerServices controllerServices = CApStopZeroUtilities.GetControllerServices(this._robot);
    controllerServices.Init(this._robot as TxRobot);
    return controllerServices.GetRrsWorldFrame().AbsoluteLocation;
  }

  private void InitPlayer()
  {
    this._player = new TxSimulationPlayer(false, true);
    this._player.SetOperation((ITxOperation) this._startLocation.ParentRoboticOperation);
    this._originalTimeInterval = TxApplication.Options.Motion.TimeInterval;
    this._player.TimeInterval = this._timeInterval;
    this._originalIgnoreSignals = TxApplication.Options.Simulation.IgnoreSignals;
    TxSimulationPlayer.IgnoreSignals = true;
    this._originalStopOnCollision = TxApplication.Options.Collision.StopOnCollision;
    TxApplication.Options.Collision.StopOnCollision = false;
    this._cycleTimeReport = new CApCTRToggleCmd();
    this._originalIsCycleTimeReportActivated = this._cycleTimeReport.IsCycleTimeReportActivated();
    if (this._originalIsCycleTimeReportActivated)
      this._cycleTimeReport.ActivateCycleTimeReport(false);
    this._player.SignificantTimeReached += new TxSimulationPlayer_SignificantTimeReachedEventHandler(this.SignificantTimeReached);
    TxOlpRoboticSimulationEvents.SimEvent += new TxOlpRoboticSimulationEvents.SimEventHandler(this.TxOlpRoboticSimulationEvents_SimEvent);
    this._simulationPhase = CApStopZeroMotionDataGenerator.SimulationPhase.BeforeStartLocation;
  }

  private void PlayerRestore()
  {
    TxOlpRoboticSimulationEvents.SimEvent -= new TxOlpRoboticSimulationEvents.SimEventHandler(this.TxOlpRoboticSimulationEvents_SimEvent);
    this._player.SignificantTimeReached -= new TxSimulationPlayer_SignificantTimeReachedEventHandler(this.SignificantTimeReached);
    TxRRSServicesProviderEx.StopSamplingStopMotion(this._rrsServiceProvider);
    TxRRSServicesProviderEx.RemoveStopSafetyVolumes(this._rrsServiceProvider);
    this._player.Rewind();
    if (this._originalIsCycleTimeReportActivated)
      this._cycleTimeReport.ActivateCycleTimeReport(true);
    TxApplication.Options.Collision.StopOnCollision = this._originalStopOnCollision;
    TxSimulationPlayer.IgnoreSignals = this._originalIgnoreSignals;
    this._player.TimeInterval = this._originalTimeInterval;
  }

  private void InitRRS()
  {
    this._rrsServiceProvider = new TxRRSServicesProvider(this._robot as TxRobot);
    this._rrsServiceProvider.ModifyRCSData((TxRRSStorageType) 1, "SIMULATE_STOP0_ACCURACY", this._accuracyMode ? "ACCURATE" : "QUICK");
    this._isRCSTurnedOffForSimulationActions = this._robot.IsRCSTurnedOffForSimulationActions;
    if (this._isRCSTurnedOffForSimulationActions)
      this._robot.IsRCSTurnedOffForSimulationActions = false;
    this._rrsWorldFrame = this.GetRrsFrame();
  }

  private void RestoreRRS()
  {
    this._robot.IsRCSTurnedOffForSimulationActions = this._isRCSTurnedOffForSimulationActions;
  }

  private void TxOlpRoboticSimulationEvents_SimEvent(TxOlpCTREventInfo simulationEvent)
  {
    this.StopGenerationIfRequested();
    switch (this._simulationPhase)
    {
      case CApStopZeroMotionDataGenerator.SimulationPhase.BeforeStartLocation:
        this.MotionToStartLocation(simulationEvent);
        break;
      case CApStopZeroMotionDataGenerator.SimulationPhase.Sampling:
        this.MotionToEndLocation(simulationEvent);
        break;
    }
  }

  public void MotionToStartLocation(TxOlpCTREventInfo simulationEvent)
  {
    if (!CApStopZeroMotionDataGenerator.IsMotionToLocationFinished(simulationEvent, (ITxLocationOperation) this._startLocation))
      return;
    this._progressReporter.ReportLocationProgress(this._startLocation, true);
    this._simulationPhase = CApStopZeroMotionDataGenerator.SimulationPhase.Sampling;
    TxRRSServicesProviderEx.StartSamplingStopMotion(this._rrsServiceProvider, this._stopType);
  }

  private void MotionToEndLocation(TxOlpCTREventInfo simulationEvent)
  {
    this._progressReporter.ReportLocationProgress(simulationEvent.EventObject1 as ITxRoboticLocationOperation, false);
    if (!CApStopZeroMotionDataGenerator.IsMotionToLocationFinished(simulationEvent, (ITxLocationOperation) this._endLocation))
      return;
    this._simulationPhase = CApStopZeroMotionDataGenerator.SimulationPhase.AfterEndLocation;
    TxOlpRoboticSimulationEvents.SimEvent -= new TxOlpRoboticSimulationEvents.SimEventHandler(this.TxOlpRoboticSimulationEvents_SimEvent);
    this._isDataGenerationSuccessful = true;
  }

  private void StopGenerationIfRequested()
  {
    this._progressReporter.ReportNonPrgress();
    if (!this._isGenerationStopped())
      return;
    this.CancelGeneration();
  }

  private void CancelGeneration()
  {
    this._isDataGenerationSuccessful = false;
    this._simulationPhase = CApStopZeroMotionDataGenerator.SimulationPhase.Cancelled;
    this.StopGeneration();
  }

  private void StopGeneration()
  {
    this._player.Stop();
    TxRRSServicesProviderEx.StopSamplingStopMotion(this._rrsServiceProvider);
  }

  private void SignificantTimeReached(
    object sender,
    TxSimulationPlayer_SignificantTimeReachedEventArgs args)
  {
    this.StopGenerationIfRequested();
    switch (this._simulationPhase)
    {
      case CApStopZeroMotionDataGenerator.SimulationPhase.Sampling:
        this.GetCurrentSafetyVolume();
        break;
      case CApStopZeroMotionDataGenerator.SimulationPhase.AfterEndLocation:
        this.StopGeneration();
        break;
    }
  }

  private void GetCurrentSafetyVolume()
  {
    List<TxRobotSimulationStopMotionData> simulationStopMotionDataList = new List<TxRobotSimulationStopMotionData>();
    try
    {
      foreach (CApStopZeroSafetyVolume safetyVolume in this._safetyVolumes)
      {
        TxRobotSimulationStopMotionData motionOfSafetyVolume = TxRRSServicesProviderEx.GetStopMotionOfSafetyVolume(this._rrsServiceProvider, safetyVolume.Id);
        motionOfSafetyVolume.CenterPositions = motionOfSafetyVolume.CenterPositions.ConvertAll<TxTransformation>((Converter<TxTransformation, TxTransformation>) (x => TxTransformation.op_Multiply(this._rrsWorldFrame, x)));
        simulationStopMotionDataList.Add(motionOfSafetyVolume);
      }
      this._stopMotionData.Add(simulationStopMotionDataList);
    }
    catch
    {
    }
  }

  private static bool IsMotionToLocationFinished(
    TxOlpCTREventInfo simulationEvent,
    ITxLocationOperation location)
  {
    return CApStopZeroMotionDataGenerator.IsMotionToLocationEvent(simulationEvent) && simulationEvent.Status == null && simulationEvent.EventObject1 == location;
  }

  private static bool IsMotionToLocationEvent(TxOlpCTREventInfo simulationEvent)
  {
    TxOlpCTRInternalEvent result;
    return Enum.TryParse<TxOlpCTRInternalEvent>(simulationEvent.EventName, out result) && result == 0;
  }

  private enum SimulationPhase
  {
    None,
    BeforeStartLocation,
    Sampling,
    AfterEndLocation,
    Cancelled,
  }
}
